#pragma once

#include <iostream>
#include <cassert>
#include <cstring>
#include <algorithm>
using namespace std;

namespace xsc
{
	template <typename T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;

		//Capacity
		size_t size() const
		{
			return _finish - _start;
		}

		size_t capacity() const
		{
			return _end_of_storage - _start;
		}

		bool empty() const
		{
			return (_finish == _start);
		}

		void reserve(size_t n)
		{
			//当将tmp赋值给_start时，_finish还没有变，此时size()就已经发生了变化，导致_finish结果是空
			if (n > capacity())
			{
				T* tmp = new T[n];
				size_t oldsize = size();
				//memmove(tmp, _start, size() * sizeof(T));//memmove是浅拷贝
				size_t i = 0;
				for (; i < size(); i++)
				{
					tmp[i] = _start[i];
				}
				delete[]_start;

				_start = tmp;
				_finish = tmp + oldsize;
				_end_of_storage = tmp + n;
			}
		}

		void resize(size_t n, T val = T())
		{
			if (n < size())
			{
				_finish = _start + n;
			}
			else
			{
				if (n > capacity())
				{
					reserve(n);
				}

				auto itor = end();
				while (itor < end() + n)
				{
					*itor = val;

					++itor;
				}
				_finish = _start + n;
			}

		}
		//iterator
		iterator begin()
		{
			return _start;
		}
		iterator end()
		{
			return _finish;
		}

		const_iterator begin() const
		{
			return _start;
		}
		const_iterator end() const
		{
			return _finish;
		}

		//access
		T& operator[](size_t n)
		{
			return *(_start + n);
		}
		const T& operator[](size_t n) const
		{
			return *(_start + n);
		}

		//constructor
		/*vector(size_t n, const T& val = T())
		{

		}*/
		/*vector()
			:_start(0), _finish(0), _end_of_storage(0)
		{}*/

		//C++11强制生成默认构造
		vector() = default;

		vector(const vector<T>& v)
		{
			reserve(v.size());
			for (auto e : v)
			{
				push_back(e);
			}
		}

		vector(size_t n, const T& t = T())
		{
			reserve(n);
			size_t i = 0;
			for (; i < n; i++)
			{
				push_back(t);
			}
		}

		vector<T>& operator=(vector<T> v)
		{
			swap(v);

			return *this;
		}

		~vector()
		{
			delete[]_start;
			_start = nullptr;
			_finish = nullptr;
			_end_of_storage = nullptr;
		}

		//modifiers
		void push_back(const T& val)
		{
			if (_finish == _end_of_storage)
			{
				//扩容
				reserve(_end_of_storage == 0 ? 4 : 2 * capacity());
			}
			*(_finish) = val;
			++_finish;
		}

		void pop_back()
		{
			assert(!empty());

			--_finish;
		}

		auto insert(iterator postion, const T& val);
		auto erase(iterator position);

		void clear()
		{
			_finish = _start;
		}

		void swap(vector<T> v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_end_of_storage,v._end_of_storage);
		}

		void printvector()
		{
			for (auto e : *this)
			{
				cout << e << " ";
			}
			cout << endl;
		}

		template<typename Container>
		void Print_Container()
		{
			for (auto e : *this)
			{
				cout << e << " ";
			}
			cout << endl;
		}

	private:
		iterator _start = nullptr;
		iterator _finish = nullptr;
		iterator _end_of_storage = nullptr;
	};

	//template <typename T>
	//void vector<T>::insert(iterator position, const T& val)
	//{
	//	assert(position <= _finish);

	//	if (_finish == _end_of_storage)
	//	{
	//		//扩容之后，position还指向之前的那块空间，要更新position到新的空间上
	//		size_t len = position - _start;

	//		//扩容
	//		reserve(_end_of_storage == 0 ? 4 : 2 * capacity());

	//		position = _start + len;
	//	}
	//	auto itor = end() - 1;
	//	while (itor >= position)
	//	{
	//		*(itor + 1) = *itor;
	//		--itor;
	//	}

	//	*position = val;
	//	++_finish;
	//}

	template <typename T>
	auto vector<T>::insert(iterator position, const T& val)
	{
		assert(position <= _finish);
		assert(position >= _start);

		if (_finish == _end_of_storage)
		{
			//扩容之后，position还指向之前的那块空间，要更新position到新的空间上
			size_t len = position - _start;

			//扩容
			reserve(_end_of_storage == 0 ? 4 : 2 * capacity());

			position = _start + len;
		}
		auto itor = end() - 1;
		while (itor >= position)
		{
			*(itor + 1) = *itor;
			--itor;
		}

		*position = val;
		++_finish;

		return position;
	}
	template<typename T>
	auto vector<T>::erase(iterator position)
	{
		assert(position < _finish);
		assert(position >= _start);

		auto itor = position;
		while (itor != end() - 1)
		{
			*itor = *(itor + 1);

			++itor;
		}
		--_finish;
		return position;
	}

}